/*
Script: Awf.historyManager.js
	This is a simple and small history manager

License:
	MIT-style license.

Authors:
	Arian Stolwijk
*/

Element.Properties.contentText = {
	get: function(){
		if (this.get('tag') == 'iframe') {
			return $(this.contentWindow.document.body).get('text');
		}
	},
	
	set: function(text){
		if (this.get('tag') == 'iframe') {
			try {
				var doc = this.contentWindow.document;
				doc.open();
				doc.write('<html><body>' + text + '</body></html>');
				doc.close();
			} 
			catch (e) { };
		}
	}
};

String.implement('parseFragment',function(argumentSeparator,keyValueSeparator){
	argumentSeparator = $pick(argumentSeparator,';');
	keyValueSeparator = $pick(keyValueSeparator,':');
	
	var o = new Hash();
	this.split(argumentSeparator).each(function(argument){
		argument = argument.split(keyValueSeparator);
		if (argument.length >= 2) {
			o.set(argument[0], argument[1]);
		} else if (argument.length == 1) {
			o.set(argument[0], null);
		}
	});
	return o;
	
});

var Awf = $merge({
	historyManager: new Class({
		version: 2.0,
		
		state: '',
		callbacks: new Hash(),
		
		IFrameState: '',
		
		Implements: [Options, Events],
		
		options: {
			delay: 200,
			defaultHash: {},
			argumentSeparator: ';',
			keyValueSeparator: ':',
			
			// This is required
			ieIFrameSrc: 'blank.html',
			// Events
			onStart: $empty(),
			onStop: $empty(),
			onStateChange: $empty()
		},
		
		initialize: function(options){
			this.setOptions(options);
			this.options.defaultHash = new Hash(this.options.defaultHash);
			
			$each(window.history,function(hist){
				$('debug').set('html',$('debug').get('html')+'<br />'+hist);
			});
			
			if (Browser.Engine.trident) {
				this.iframe = new IFrame({
					src: this.options.ieIFrameSrc,
					styles: {
						width: 1,
						height: 1,
						border: 0,
						visibility: 'hidden'
					}
				}).inject(document.body);
			}			
		},
		
		register: function(key, callback){
			if ($type(callback) == 'function') {
				this.callbacks[key] = callback;
			}
			return this;
		},
		
		unregister: function(key){
			this.callbacks.erase(key);
		},
		
		start: function(){
			this.timer = this.observe.periodical(this.options.delay, this);
			this.observe();
			this.fireEvent('onStart');
		},
		
		stop: function(){
			$clear(this.timer);
			this.fireEvent('onStop');
		},
		
		observe: function(){
			var state = this.getFragment();
			
			if (this.iframe) {
				if(state != this.state){
					this.iframe.set('contentText',state);
				}else{
					var IFrameState = this.iframe.get('contentText');
					if(IFrameState != this.IFrameState){
						if (IFrameState) {
							top.location.hash = '#' + IFrameState;
							this.IFrameState = state = IFrameState;
						}
					}
				}
			}

			var tmpHash = this.state.parseFragment(
				this.options.argumentSeparator,
				this.options.keyValueSeparator
			);

			var currentHash = state.parseFragment(
				this.options.argumentSeparator,
				this.options.keyValueSeparator
			);			
			
			$each(this.callbacks, function(fn, key){
				if (currentHash.has(key)) {
					var value = currentHash.get(key);
				} else if (this.options.defaultHash.has(key)) {
					var value = this.options.defaultHash.get(key);
				}
				if (value != tmpHash.get(key)) {
					fn(value, key, tmpHash);
					this.fireEvent('onStateChange', [value, key, tmpHash]);
				}
			}, this);
			
			// for the next iteration
			this.state = state;
		},
		
		getFragment: function(){
			var href = top.location.href;
			var pos = href.indexOf('#') + 1;
			return (pos) ? href.substr(pos) : '';
		}
		
	})
}, Awf ||
{});
